package com.quanyan.financialSystem.service.place.impl;

import com.quanyan.common.Plugin.Page;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.utils.TimeUtils;
import com.quanyan.financialSystem.entity.db.*;
import com.quanyan.financialSystem.entity.vo.req.*;
import com.quanyan.financialSystem.entity.vo.resp.*;
import com.quanyan.financialSystem.mapper.*;
import com.quanyan.financialSystem.service.place.PlaceBizSettleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.SimpleAutowireCandidateResolver;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by yuanxuebing on 16-10-21.
 */
@Service
public class PlaceBizSettleServiceImpl implements PlaceBizSettleService {

    private static final Logger logger = LoggerFactory.getLogger(PlaceBizSettleServiceImpl.class);

    @Autowired
    private TbBizPlaceOrderMapper placeOrderMapper;

    @Autowired
    private TbBizPlaceMemberOpHistoryMapper opHistoryMapper;

    @Autowired
    private TbBizStatementsMapper statementsMapper;

    @Autowired
    private TbBizStatementDetailMapper statementDetailMapper;

    @Autowired
    private StatementRunnnigNumMapper runningNumMapper;

    @Autowired
    private PlaceCashUnSettleOrderMapper unSettleOrderMapper;

    @Value("${settle.account}")
    private String settleAccount;

    StatementBaseInfo constructBaseInfo(TbBizStatements statement) {
        if (statement == null) {
            return null;
        }

        StatementBaseInfo baseInfo = new StatementBaseInfo();

        baseInfo.setId(statement.getId());
        baseInfo.setStatementId(statement.getStatementId());
        baseInfo.setPlaceId(statement.getPlaceId());
        baseInfo.setTotalAmount(statement.getTotalAmount());
        baseInfo.setCreateName(statement.getCreateName());
        baseInfo.setCreateDate(statement.getCreateDate());
        baseInfo.setTransferName(statement.getTransferName());
        baseInfo.setTransferDate(statement.getTransferDate());
        baseInfo.setStatementStatus(statement.getStatementStatus());
        baseInfo.setSettleName(statement.getSettleName());
        baseInfo.setSettleDate(statement.getSettleDate());
        baseInfo.setBankAccount(statement.getBankAccount());
        baseInfo.setTransferRemark(statement.getTransferRemark());
        baseInfo.setSettleRemark(statement.getSettleRemark());

        return baseInfo;
    }

    SettleOrder newSettleOrderFromTbPlaceOrder(TbBizPlaceOrder tovo, int flag) {
        SettleOrder ovo = new SettleOrder();

        ovo.setOrderId(tovo.getId());
        ovo.setOrderNo(tovo.getPlaceOrderId());
        ovo.setOrderType((byte) 1);  //普通订单
        ovo.setOrderStatus(tovo.getOrderStatus());

        // 由订单状态决定
        if (flag == 0) {
            if (tovo.getOrderStatus() == 5) {
                flag = 2;
            } else {
                flag = 1;
            }
        }

        // 算收入
        if (flag == 1)
        {
            ovo.setPayAmount(tovo.getDebit());
            int i = tovo.getDebit().compareTo(BigDecimal.ZERO);
            if (i == 1) {
                ovo.setPayAmount(tovo.getDebit());
            } else if (i == 0 || i == -1) {  // 注意退款会把debit置零
                int j = tovo.getCredit().compareTo(BigDecimal.ZERO);
                if (j == 1) {
                    ovo.setPayAmount(tovo.getCredit());
                }
            }
            ovo.setPaymentTime(tovo.getPaymentTime());
        }
        // 算支出
        else if (flag == 2){
            BigDecimal munusCredit = tovo.getCredit().multiply(new BigDecimal(-1));
            ovo.setPayAmount(munusCredit);
            ovo.setPaymentTime(tovo.getRefundTime());
        }

        ovo.setDebit(tovo.getDebit());
        ovo.setCredit(tovo.getCredit());
        ovo.setCashStatus(tovo.getCashStatus());
        ovo.setRefundCashStatus(tovo.getRefundCashStatus());

        return ovo;
    }

    SettleOrder newSettleOrderFromTbMemberOpHistory(TbBizPlaceMemberOpHistory tovo) {
        SettleOrder ovo = new SettleOrder();

        ovo.setOrderId(tovo.getId());
        ovo.setOrderNo(tovo.getOrderNo());
        ovo.setOrderType((byte) 2);  //　充值订单
        ovo.setOrderStatus((byte) 6); // 充值已经完成
        ovo.setPayAmount(tovo.getAmount());
        ovo.setPaymentTime(tovo.getCreateTime());
        ovo.setCashStatus(tovo.getCashStatus());

        // 新增字段
        ovo.setDebit(tovo.getAmount());
        ovo.setCredit(BigDecimal.ZERO);

        return ovo;
    }

    // 批量查询普通订单
    List<SettleOrder> batchNormalOrders(Integer placeId, List<Integer> ids) {
        List<SettleOrder> settleOrderList = new ArrayList<SettleOrder>();

        if (ids == null || ids.size() <= 0) {
            return settleOrderList;
        }

        TbBizPlaceOrderExample rExample = new TbBizPlaceOrderExample();
        TbBizPlaceOrderExample.Criteria rCriteria = rExample.createCriteria();
        rCriteria.andPlaceIdEqualTo(placeId);
        rCriteria.andIdIn(ids);

        List<TbBizPlaceOrder> tbOrderList = placeOrderMapper.selectByExample(rExample);
        for (TbBizPlaceOrder tovo : tbOrderList) {
            SettleOrder ovo = this.newSettleOrderFromTbPlaceOrder(tovo, 0);
            settleOrderList.add(ovo);
        }

        return settleOrderList;
    }

    // 批量查询会员订单
    List<SettleOrder> batchMemberOrders(Integer placeId, List<Integer> ids) {
        List<SettleOrder> settleOrderList = new ArrayList<SettleOrder>();

        if (ids == null || ids.size() <=0) {
            return settleOrderList;
        }

        TbBizPlaceMemberOpHistoryExample rExample = new TbBizPlaceMemberOpHistoryExample();
        TbBizPlaceMemberOpHistoryExample.Criteria rCriteria = rExample.createCriteria();
        rCriteria.andPlaceIdEqualTo(placeId);
        rCriteria.andIdIn(ids);

        List<TbBizPlaceMemberOpHistory> tbBizPlaceMemberOpHistoryList = opHistoryMapper.selectByExample(rExample);
        for (TbBizPlaceMemberOpHistory tovo : tbBizPlaceMemberOpHistoryList) {
            SettleOrder ovo = this.newSettleOrderFromTbMemberOpHistory(tovo);
            settleOrderList.add(ovo);
        }

        return settleOrderList;
    }

    // 获取未结算的普通订单
    List<SettleOrder> listUnSettleNormalOrders(Integer placeId, Date startDate, Date endDate) {
        // 所有收入的订单
        List<Byte> validStatus = new ArrayList<Byte>();
        validStatus.add((byte) 3);
        validStatus.add((byte) 4);
        validStatus.add((byte) 5);
        validStatus.add((byte) 6);

        TbBizPlaceOrderExample rExample = new TbBizPlaceOrderExample();
        TbBizPlaceOrderExample.Criteria rCriteria = rExample.createCriteria();
        rCriteria.andPlaceIdEqualTo(placeId);
        rCriteria.andOrderStatusIn(validStatus);
        rCriteria.andCashStatusEqualTo((byte) 1);  // 收入结算状态为未申请的订单
        rCriteria.andPaymentTimeBetween(startDate, endDate);
        rCriteria.andSourceTypeEqualTo((byte) 2);  // 只考虑现金支付的

        List<TbBizPlaceOrder> tbOrderList = placeOrderMapper.selectByExample(rExample);
        List<SettleOrder> settleOrderList = new ArrayList<SettleOrder>();
        for (TbBizPlaceOrder tovo : tbOrderList) {
            SettleOrder ovo = this.newSettleOrderFromTbPlaceOrder(tovo, 1);
            settleOrderList.add(ovo);
        }

        // 所有支出的订单
        TbBizPlaceOrderExample rExample2 = new TbBizPlaceOrderExample();
        TbBizPlaceOrderExample.Criteria rCriteria2 = rExample2.createCriteria();
        rCriteria2.andPlaceIdEqualTo(placeId);
        rCriteria2.andOrderStatusEqualTo((byte) 5);         // 订单类型是已退款的
        rCriteria2.andRefundCashStatusEqualTo((byte) 1);    // 支出结算状态为未申请的订单
        rCriteria2.andRefundTimeBetween(startDate, endDate);
        rCriteria2.andSourceTypeEqualTo((byte) 2);          // 现场现金支付

        List<TbBizPlaceOrder> tbOrderList2 = placeOrderMapper.selectByExample(rExample2);
        for (TbBizPlaceOrder tovo : tbOrderList2) {
            SettleOrder ovo = this.newSettleOrderFromTbPlaceOrder(tovo, 2);
            settleOrderList.add(ovo);
        }

        return settleOrderList;
    }

    // 获取未结算的会员订单
    List<SettleOrder> listUnSettleMemberOrders(Integer placeId, Date startDate, Date endDate) {
        TbBizPlaceMemberOpHistoryExample rExample = new TbBizPlaceMemberOpHistoryExample();
        TbBizPlaceMemberOpHistoryExample.Criteria rCriteria = rExample.createCriteria();
        rCriteria.andPlaceIdEqualTo(placeId);
        rCriteria.andAdminPayTypeEqualTo((byte) 20);
        rCriteria.andCashStatusEqualTo((byte) 1);  // 结算状态为未申请的订单
        rCriteria.andCreateTimeBetween(startDate, endDate);

        List<TbBizPlaceMemberOpHistory> tbBizPlaceMemberOpHistoryList = opHistoryMapper.selectByExample(rExample);
        List<SettleOrder> settleOrderList = new ArrayList<SettleOrder>();
        for (TbBizPlaceMemberOpHistory tovo : tbBizPlaceMemberOpHistoryList) {
            SettleOrder ovo = this.newSettleOrderFromTbMemberOpHistory(tovo);
            settleOrderList.add(ovo);
        }

        return settleOrderList;
    }

    // 更新普通账单结算状态(refund:是否是退款订单)
    int updateNormalOrderSettleStatus(List<Integer> ids, List<String> orderNOs, byte newStatus, boolean refund) {
        if ((ids == null || ids.size() <= 0) && (orderNOs == null || orderNOs.size() <= 0)) {
            return -1;
        }

        TbBizPlaceOrder voOrder = new TbBizPlaceOrder();
        if (refund) {
            voOrder.setRefundCashStatus(newStatus); // 退款的就更新退款结算状态
        } else {
            voOrder.setCashStatus(newStatus);
        }

        TbBizPlaceOrderExample poExample = new TbBizPlaceOrderExample();
        TbBizPlaceOrderExample.Criteria poCriteria = poExample.createCriteria();

        if (ids != null && ids.size() > 0) {
            poCriteria.andIdIn(ids);

        }

        if (orderNOs != null && orderNOs.size() > 0) {
            poCriteria.andPlaceOrderIdIn(orderNOs);
        }

        return placeOrderMapper.updateByExampleSelective(voOrder, poExample);
    }

    // 更新会员订单结算状态
    int updateMemberOrderSettleStatus(List<Integer> ids, List<String> orderNOs, byte newStatus) {
        if ((ids == null || ids.size() <= 0) && (orderNOs == null || orderNOs.size() <= 0)) {
            return -1;
        }

        TbBizPlaceMemberOpHistory opHistory = new TbBizPlaceMemberOpHistory();
        opHistory.setCashStatus(newStatus);

        TbBizPlaceMemberOpHistoryExample ophExample = new TbBizPlaceMemberOpHistoryExample();
        TbBizPlaceMemberOpHistoryExample.Criteria ophCriteria = ophExample.createCriteria();

        if (ids != null && ids.size() > 0) {
            ophCriteria.andIdIn(ids);
        }

        if (orderNOs != null && orderNOs.size() > 0) {
            ophCriteria.andOrderNoIn(orderNOs);
        }

        return opHistoryMapper.updateByExampleSelective(opHistory, ophExample);
    }

    static public String createMapKey(Byte orderType, Integer id) {
        return String.format("%d_%d", orderType, id);
    }

    @Override
    public List<SettleOrder> listUnSettleOrders(ReqListUnSettleOrders reqVo) {
        Integer placeId = reqVo.getPlaceId();
        Date startDate = reqVo.getPayStartDate();
        Date tmp = reqVo.getPayEndDate();
        Date endDate = TimeUtils.getDateAfterSeconds(tmp, (24*60*60 - 1));
        reqVo.setPayEndDate(endDate);

        List<SettleOrder> allOrders = new ArrayList<>();
        //List<SettleOrder> normalOrders = this.listUnSettleNormalOrders(placeId, startDate, endDate);    // 普通订单
        List<SettleOrder> normalOrders = unSettleOrderMapper.listUnSettleNormalOrders(reqVo);
        List<SettleOrder> memberOrders = this.listUnSettleMemberOrders(placeId, startDate, endDate);    // 会员充值订单
        allOrders.addAll(normalOrders);
        allOrders.addAll(memberOrders);
        logger.info("req:[{}] result:[{}/{}/{}]", reqVo, allOrders.size(), normalOrders.size(), memberOrders.size());

        return allOrders;
    }

    @Override
    public RespCreateStatement createStatement(ReqCreateStatement reqVo) {
        List<Integer> debitIds = new ArrayList<Integer>();   // 收入单集合
        List<Integer> creditIds = new ArrayList<Integer>();  // 支出单集合
        List<Integer> normalIds = new ArrayList<Integer>();  // 所有普通订单集合
        List<Integer> memberIds = new ArrayList<Integer>();

        if (reqVo.getUnSettleOrders() != null && reqVo.getUnSettleOrders().size() > 0) {
            for (SettleOrder order : reqVo.getUnSettleOrders()) {
                Byte orderType = order.getOrderType();
                if (orderType == 1) {
                    normalIds.add(order.getOrderId());

                    int ret = order.getPayAmount().compareTo(BigDecimal.ZERO);
                    if ( ret == 1 || ret == 0) {    // 收入单
                        debitIds.add(order.getOrderId());
                    } else {                        // 支出单
                        creditIds.add(order.getOrderId());
                    }
                } else if (orderType == 2) {
                    memberIds.add(order.getOrderId());
                }
            }
        }

        // 安全起见金额需要验证一下，订单状态也需要验证一下，避免重复结算
        Map<String,SettleOrder> map = new HashMap<>();
        List<SettleOrder> normalOrders = this.batchNormalOrders(reqVo.getPlaceId(), normalIds);
        if (normalOrders != null && normalOrders.size() > 0) {
            for (SettleOrder nOrder : normalOrders) {
                String mapKey = this.createMapKey(nOrder.getOrderType(), nOrder.getOrderId());
                map.put(mapKey, nOrder);
            }
        }

        List<SettleOrder> memberOrders = this.batchMemberOrders(reqVo.getPlaceId(), memberIds);
        if (memberOrders != null && memberOrders.size() > 0) {
            for (SettleOrder mOrder : memberOrders) {
                String mapKey = this.createMapKey(mOrder.getOrderType(), mOrder.getOrderId());
                map.put(mapKey, mOrder);
            }
        }

        BigDecimal dbTotalAmount = BigDecimal.valueOf(0);
        BigDecimal reqTotalAmount =  BigDecimal.valueOf(0);
        if (reqVo.getUnSettleOrders() != null && reqVo.getUnSettleOrders().size() > 0) {
            for (SettleOrder order : reqVo.getUnSettleOrders()) {
                String mapKey = this.createMapKey(order.getOrderType(), order.getOrderId());
                SettleOrder dbOrder = map.get(mapKey);
                if (dbOrder == null) {
                    return new RespCreateStatement(
                            String.format("订单:%s 不存在", order.getOrderNo()), null);
                }

                // 只有未结算的订单才可以创建结算
                if (dbOrder.getCashStatus() != 1 && dbOrder.getRefundCashStatus() != 1 ) {
                    return new RespCreateStatement(
                            String.format("订单%s不是未结算状态", order.getOrderNo()), null);
                }

                int i = order.getPayAmount().compareTo(BigDecimal.ZERO);
                if (i == 1) {  // > 0
                    BigDecimal realDebit = dbOrder.getDebit();
                    // 退款的订单，Debit被清零了
                    if (realDebit.compareTo(BigDecimal.ZERO)  == 0) {
                        realDebit = order.getPayAmount(); // 选择相信前端的数据
                    }
                    dbTotalAmount = dbTotalAmount.add(realDebit);
                } else if (i == -1) {
                    BigDecimal credit = dbOrder.getCredit().multiply(new BigDecimal(-1));
                    dbTotalAmount = dbTotalAmount.add(credit);
                }
                reqTotalAmount = reqTotalAmount.add(order.getPayAmount());
            }
        }

        if (dbTotalAmount.compareTo(reqVo.getTotalAmount()) != 0 || reqTotalAmount.compareTo(reqVo.getTotalAmount()) != 0 ) {
            return new RespCreateStatement(
                    String.format("总金额不对!"), null);
        }

        TbBizStatements tbStatement = new TbBizStatements();

        // 系统生成结算单号:一共12位，XJ（前辍）+ 161017（年月日）+ 0001（自增流水号），如：XJ1610170001
        if (reqVo.getCreateDate() == null) {
            reqVo.setCreateDate(new Date());
        }

        java.text.DateFormat format = new java.text.SimpleDateFormat("yyyyMMdd");
        String createDateStr = format.format(reqVo.getCreateDate());

        String RNKey = String.format("XJ%s", createDateStr);
        int suffix = runningNumMapper.getNextRunningNum(RNKey);
        String statementNo = String.format("XJ%s%04d", createDateStr, suffix);
        tbStatement.setStatementId(statementNo);
        tbStatement.setPlaceId(reqVo.getPlaceId());
        tbStatement.setTotalAmount(reqVo.getTotalAmount());
        tbStatement.setCreateName(reqVo.getCreateName());
        tbStatement.setCreateDate(reqVo.getCreateDate());
        tbStatement.setStatementStatus((byte) 1); // 设置结算单为申请结算
        if (this.settleAccount != null) {
            tbStatement.setBankAccount(this.settleAccount);    // 银行账号从配置读取
        } else {
            String defaultAccount = "招商银行一般户【7559 2904 6910 501】招商银行股份有限公司深圳创维大厦支行";
            tbStatement.setBankAccount(defaultAccount);
        }

        // 保存结算单基本信息
        int ret = statementsMapper.insertSelective(tbStatement);
        if (ret < 1) {
            return new RespCreateStatement(
                    String.format("插入结算单失败!"), null);
        }
        int id = tbStatement.getId();

        // 添加结算详情,此处改成批量添加比较好
        if (reqVo.getUnSettleOrders() != null && reqVo.getUnSettleOrders().size() > 0) {
            for (SettleOrder order : reqVo.getUnSettleOrders()) {
                Byte orderType = order.getOrderType();

                TbBizStatementDetail detail = new TbBizStatementDetail();
                detail.setStatementId(id);
                detail.setPlaceOrderId(order.getOrderNo());
                detail.setOrderType(orderType);
                // 把金额和支付时间一起存入数据表中
                detail.setHandleMoney(order.getPayAmount());
                detail.setPayTime(order.getPaymentTime());
                // 这里可以考虑保存一下订单是 收入 还是 支出 的标志,暂时通过金额来判断

                statementDetailMapper.insertSelective(detail);
            }
        }

        // 将已经结算的订单的结算状态设置为 “申请结算”
        if (debitIds.size() > 0) {
            this.updateNormalOrderSettleStatus(debitIds, null, (byte) 2, false);
        }

        if (creditIds.size() > 0) {
            this.updateNormalOrderSettleStatus(creditIds, null, (byte) 2, true);
        }

        if (memberIds.size() > 0) {
            this.updateMemberOrderSettleStatus(memberIds, null, (byte) 2);
        }

        TbBizStatements result = statementsMapper.selectByPrimaryKey(id);
        StatementBaseInfo baseInfo = this.constructBaseInfo(result);

        return new RespCreateStatement(null, baseInfo);
    }

    @Override
    public PageObj<List<StatementBaseInfo>> listPlaceStatements(ReqListPlaceStatements reqVo) {
        Integer pageNum = 0;
        Integer pageSize = 30;   // 默认每页30

        if (reqVo != null) {
            if (reqVo.getPageNum() != null) {
                pageNum = reqVo.getPageNum();
            }
            if (reqVo.getPageSize() != null) {
                pageSize = reqVo.getPageSize();
            }
        }

        List<StatementBaseInfo> baseInfos = new ArrayList<StatementBaseInfo>();

        TbBizStatementsExample rExample = new TbBizStatementsExample();
        TbBizStatementsExample.Criteria rCriteria = rExample.createCriteria();
        rCriteria.andPlaceIdEqualTo(reqVo.getPlaceId());
        if (reqVo.getStatementStatus() > 0) {
            rCriteria.andStatementStatusEqualTo(reqVo.getStatementStatus());
        }

        if (reqVo.getCreateStartDate() != null) {
            rCriteria.andCreateDateGreaterThanOrEqualTo(reqVo.getCreateStartDate());
        }
        if (reqVo.getCreateEndDate() != null) {
            rCriteria.andCreateDateLessThanOrEqualTo(reqVo.getCreateEndDate());
        }

        if (reqVo.getSettleStartDate() != null) {
            rCriteria.andSettleDateGreaterThanOrEqualTo(reqVo.getSettleStartDate());
        }
        if (reqVo.getSettleEndDate() != null) {
            rCriteria.andSettleDateLessThanOrEqualTo(reqVo.getSettleEndDate());
        }

        // 先获取总数
        int totalNum = statementsMapper.countByExample(rExample);

        // 分页
        rExample.setOrderByClause("id DESC");
        Page page = new Page(pageNum * pageSize, pageSize, totalNum);
        rExample.setPage(page);

        List<TbBizStatements> statements = statementsMapper.selectByExample(rExample);
        if (statements != null) {
            for (TbBizStatements statement : statements) {
                baseInfos.add(this.constructBaseInfo(statement));
            }
        }

        PageObj<List<StatementBaseInfo>> result = PageObj.create(totalNum, pageNum, pageSize, baseInfos);

        return result;
    }

    @Override
    public StatementInfo getStatementInfo(ReqGetStatementInfo reqVo) {
        TbBizStatements statement = statementsMapper.selectByPrimaryKey(reqVo.getId());
        if (statement == null) {
            return null;
        }
        StatementBaseInfo baseInfo = this.constructBaseInfo(statement);

        // 获取结算单明细
        List<SettleOrder> orders = new ArrayList<SettleOrder>();
        TbBizStatementDetailExample sdExample = new TbBizStatementDetailExample();
        TbBizStatementDetailExample.Criteria sdCriteria = sdExample.createCriteria();
        sdCriteria.andStatementIdEqualTo(reqVo.getId());

        List<TbBizStatementDetail> details = statementDetailMapper.selectByExample(sdExample);
        if (details != null) {
            for (TbBizStatementDetail detail : details) {
                SettleOrder order = new SettleOrder();

                order.setOrderNo(detail.getPlaceOrderId());
                order.setOrderType(detail.getOrderType());
                order.setPayAmount(detail.getHandleMoney());
                order.setPaymentTime(detail.getPayTime());

                orders.add(order);
            }
        }

        StatementInfo sInfo = new StatementInfo();
        sInfo.setBaseInfo(baseInfo);
        sInfo.setOrders(orders);

        return sInfo;
    }

    @Override
    public RespSaveTransferRemark saveTransferRemark(ReqSaveTransferRemark reqVo) {
        TbBizStatements oldStatement = statementsMapper.selectByPrimaryKey(reqVo.getId());
        if (oldStatement == null) {
            return new RespSaveTransferRemark("结算单不存在", null);
        }

        TbBizStatements voStatement = new TbBizStatements();
        voStatement.setTransferRemark(reqVo.getTransferRemark());

        TbBizStatementsExample sExample = new TbBizStatementsExample();
        TbBizStatementsExample.Criteria sCriteria = sExample.createCriteria();
        sCriteria.andIdEqualTo(reqVo.getId());

        int ret = statementsMapper.updateByExampleSelective(voStatement, sExample);
        if (ret < 1) {
            return new RespSaveTransferRemark("更新结算单数据库失败!", null);
        }

        // 数据库中读取最新Baseinfo返回
        TbBizStatements newStatement = statementsMapper.selectByPrimaryKey(reqVo.getId());
        if (newStatement == null) {
            return new RespSaveTransferRemark("无法找到更新后的结算单!", null);
        }
        return new RespSaveTransferRemark(null, this.constructBaseInfo(newStatement));
    }

    @Override
    public RespTransferStatement transferStatement(ReqTransferStatement reqVo) {
        // 只有处于“申请结算”的结算单，商家才可以发起转账
        TbBizStatements oldStatement = statementsMapper.selectByPrimaryKey(reqVo.getId());
        if (oldStatement == null) {
            return new RespTransferStatement("结算单不存在", null);
        }

        StatementBaseInfo oldBaseInfo = this.constructBaseInfo(oldStatement);
        if (!oldBaseInfo.canTransfer()) {
            return new RespTransferStatement("结算单状态不对", null);
        }

        // 准备更新结算单状态
        TbBizStatements voStatement = new TbBizStatements();
        voStatement.setTransferName(reqVo.getTransferName());
        voStatement.setTransferDate(reqVo.getTransferDate());
        voStatement.setTransferRemark(reqVo.getTransferRemark());
        voStatement.setStatementStatus((byte) 2); // 状态更新为已转账

        TbBizStatementsExample sExample = new TbBizStatementsExample();
        TbBizStatementsExample.Criteria sCriteria = sExample.createCriteria();
        sCriteria.andIdEqualTo(reqVo.getId());

        int ret = statementsMapper.updateByExampleSelective(voStatement, sExample);
        if (ret < 1) {
            return new RespTransferStatement("更新结算单状态失败", null);
        }

        // 将结算单内所有订单的结算状态改为已转账（注意区分普通账单和会员充值）
        TbBizStatementDetailExample sdExample = new TbBizStatementDetailExample();
        TbBizStatementDetailExample.Criteria sdCriteria = sdExample.createCriteria();
        sdCriteria.andStatementIdEqualTo(reqVo.getId());

        List<String> normalNOs = new ArrayList<String>();
        List<String> debitNOs = new ArrayList<String>();  // 收入单订单号集合
        List<String> creditNOs = new ArrayList<String>(); // 支出单订单号集合

        List<String> memberNOS = new ArrayList<String>();
        List<TbBizStatementDetail> details = statementDetailMapper.selectByExample(sdExample);
        if (details != null) {
            for (TbBizStatementDetail detail : details) {
                if (detail.getOrderType() == 1) {
                    normalNOs.add(detail.getPlaceOrderId());

                    int flag = detail.getHandleMoney().compareTo(BigDecimal.ZERO);
                    if ( flag == 1 || flag == 0) {
                        debitNOs.add(detail.getPlaceOrderId());
                    } else {
                        creditNOs.add(detail.getPlaceOrderId());
                    }
                } else if (detail.getOrderType() == 2) {
                    memberNOS.add(detail.getPlaceOrderId());
                }
            }

            // 订单状态设置为已转账
            this.updateNormalOrderSettleStatus(null, debitNOs, (byte) 3, false);
            this.updateNormalOrderSettleStatus(null, creditNOs, (byte) 3, true);
            this.updateMemberOrderSettleStatus(null, memberNOS, (byte) 3);
        }

        // 数据库中读取最新Baseinfo返回
        TbBizStatements newStatement = statementsMapper.selectByPrimaryKey(reqVo.getId());
        if (newStatement == null) {
            return new RespTransferStatement("无法找到更新后的结算单!", null);
        }
        return new RespTransferStatement(null, this.constructBaseInfo(newStatement));
    }
}